package com.oplink.webems.common.snmp.service;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Vector;

import org.snmp4j.mp.SnmpConstants;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import com.oplink.webems.common.snmp.base.SnmpApi;
import com.oplink.webems.common.snmp.base.SnmpException;
import com.oplink.webems.common.snmp.entity.Card;
import com.oplink.webems.common.snmp.entity.Dcp22Card;
import com.oplink.webems.common.snmp.entity.Dcp2Card;
import com.oplink.webems.common.snmp.entity.FanCard;
import com.oplink.webems.common.snmp.entity.Mo;
import com.oplink.webems.common.snmp.entity.Ne;
import com.oplink.webems.common.snmp.entity.PowerCard;
import com.oplink.webems.common.snmp.entity.SccCard;
import com.oplink.webems.common.snmp.security.CommBaseSecurity;
import com.oplink.webems.common.snmp.security.SnmpV1V2Community;

@Component
@Transactional
public class SnmpService implements ISnmpService {

	private SnmpApi sa;
	private String ip;

	/**
	 * 用这种方式必须执行connect/connectV2方法
	 */
	public SnmpService() {
		super();
	}

	public SnmpService(String ip, String community) {
		this.ip = ip;
		sa = new SnmpApi(ip, new SnmpV1V2Community(community, community), 161, 500, 1, SnmpConstants.version2c);
	}

	/**
	 * 支持V2c,V3的连接
	 * @param ip
	 * @param community
	 */
	public void connect(String ip, CommBaseSecurity community){
		this.ip = ip;
		sa = new SnmpApi(ip, community, 161, 1500, 1, community instanceof SnmpV1V2Community?SnmpConstants.version2c:SnmpConstants.version3);
		
	}
	
	/**
	 * 支持V2C的连接
	 * @param ip
	 * @param a
	 */
	public void connectV2(String ip, String community){
		this.ip = ip;
		sa = new SnmpApi(ip, new SnmpV1V2Community(community, community), 161, 1500, 1, SnmpConstants.version2c);
	}
	
	@Override
	public String get(Card card, String name) throws SnmpException {
		String oid = getOidByName(name, card) + getSuffix(card);
		return sa.get(oid);
	}

	@Override
	public List<String> get(Card card, List<String> nameList) throws SnmpException {
		List<String> oids = new ArrayList<String>();
		for (String name : nameList) {
			oids.add(getOidByName(name, card) + getSuffix(card));
		}
		return sa.get(oids);
	}

	@Override
	public List<Boolean> set(Card card, List<Vector<String>> nameAndValues) throws SnmpException {
		return this.set_private(card, nameAndValues);
	}

	@Override
	public Boolean set(Card card, String name, String value) throws SnmpException {
		String oid = getOidByName(name, card) + getSuffix(card);
		return sa.set(oid, value);
	}

	@Override
	public String[] getNext(Card card, String name) throws SnmpException {
		String oid = getOidByName(name, card) + getSuffix(card);
		return sa.getNext(oid);
	}

	@Override
	public List<Card> scanCards() throws SnmpException {
		List<Card> l = new ArrayList<Card>();
		Card sccTemp = new SccCard(1, 5);
		String oid = getOidByName(SccCard.GetModeConfig, sccTemp) + getSuffix(sccTemp);

		String value = sa.get(oid);
		
		//如果value有值，说明能通讯成功，则添加scc卡,power卡，fan卡，等
		l.add(new SccCard());
		l.add(new PowerCard(1, 6));
		l.add(new PowerCard(1, 7));
		l.add(new FanCard(1, 8));
		
		String[] valueArray = value.split("slot");
		for (String av : valueArray) {
			String[] avArray = av.split(" ");
			int slot = -1;
			try {
				slot = Integer.parseInt(avArray[0].trim());
			} catch (Exception e) {
				continue;
			}

			String cardType = avArray[1].trim();
			if (cardType.equals(Dcp22Card.NAME)) {
				l.add(new Dcp22Card(1, slot));
			} else if (cardType.equals(Dcp2Card.NAME)) {
				l.add(new Dcp2Card(1, slot));
			}
		}
		return l;
	}

	@Override
	public boolean addCard(Card card) throws SnmpException {
		String value = card.getSlot() + " " + card.getName();

		Card sccTemp = new SccCard(1, 5);
		String oid = getOidByName(SccCard.AddModeConfig, sccTemp) + getSuffix(sccTemp);
		return sa.set(oid, value);
	}

	@Override
	public boolean delCard(Card card) throws SnmpException {
		String value = card.getSlot() + " " + card.getName();

		Card sccTemp = new SccCard(1, 5);
		String oid = getOidByName(SccCard.DelModeConfig, sccTemp) + getSuffix(sccTemp);
		return sa.set(oid, value);
	}

	private String getOidByName(String name, Card card) throws SnmpException {
		String ret = card.getOidByName(name);
		if (ret == null) {
			throw new SnmpException(SnmpException.VALID_NAME_ERROR,this.ip, name, null,null);
		}
		return ret;
	}

	private String getSuffix(Mo m) {
		return m.getSuffix();
	}

	public static void main(String[] args) {
		final SnmpService ss = new SnmpService("172.16.166.240", "Admin@123");
		final SnmpService ss1 = new SnmpService("172.1.2.3", "Admin@123");
		final SnmpService ss2 = new SnmpService("192.16.1.3", "Admin@123");
		Thread t = new Thread(new Runnable() {
			@Override
			public void run() {
				ss.active();
			}
		});
		
		Thread t1 = new Thread(new Runnable() {
			@Override
			public void run() {
				ss1.active();
			}
		});
		
		Thread t2 = new Thread(new Runnable() {
			@Override
			public void run() {
				ss2.active();
			}
		});
		t.start();
		t1.start();
		t2.start();

		// read
		/*Card ssc = new SccCard(1, 5);
		List<String> nameList = new ArrayList<String>();
		nameList.add("CardType");
		nameList.add("HardwareRev");
		nameList.add("FirmwareRev");
		nameList.add("PCode");
		try {
			System.out.print("read result:\t");
			System.out.println(ss.get(ssc, nameList));
		} catch (SnmpException e) {
			e.printStackTrace();
		}

		// write
		Card dcp22 = new Dcp22Card(1, 1);
		List<Vector<String>> nameAndValues = new ArrayList<Vector<String>>();
		Vector<String> v1 = new Vector<String>();
		v1.add("WTRTime");
		v1.add("12");
		Vector<String> v2 = new Vector<String>();
		v2.add("Hysterisis");
		v2.add("3");
		nameAndValues.add(v1);
		nameAndValues.add(v2);
		try {
			System.out.print("write result:\t");
			System.out.println(ss.set(dcp22, nameAndValues));
		} catch (SnmpException e) {
			e.printStackTrace();
		}

		// scan cards
		List<Card> list = null;
		try {
			list = ss.scanCards();
			System.out.print("scan cards size result:\t");
			System.out.println(list.size());
		} catch (SnmpException e) {
			e.printStackTrace();
		}

		// modify card
		try {
			if ((list == null) || (list.size() == 0)) {
				Card card = new Dcp22Card(1, 1);
				System.out.print("add card result:\t");
				System.out.println(ss.addCard(card));
			} else {
				for (Card card : list) {
					System.out.print("delete card result:\t");
					System.out.println(ss.delCard(card));
				}
			}
		} catch (SnmpException e) {
			e.printStackTrace();
		}*/
	}

	@Override
	public Map<String, String> getMap(Card card, List<String> names)
			throws SnmpException {
		List<String> oids = new ArrayList<String>();
		for (String name : names) {
			oids.add(getOidByName(name, card) + getSuffix(card));
		}
		List<String> l = sa.get(oids);
		
		Map<String, String> map = new HashMap<String, String>();
		for(int i=0; i<names.size(); i++){
			map.put(names.get(i), l.get(i));
		}
		return map;
	}

	@Override
	public Map<String, Boolean> setMap(Card card, Map<String, String> _map)
			throws SnmpException {
		List<Vector<String>> nameAndValues = new ArrayList<Vector<String>>();
		
		for(String key : _map.keySet()){
			Vector<String> v = new Vector<String>();
			v.add(key);
			v.add(_map.get(key));
			nameAndValues.add(v);
		}
		
		List<Boolean> l = this.set(card, nameAndValues);
		
		Map<String, Boolean> map = new HashMap<String, Boolean>();
		
		for(int i=0; i<nameAndValues.size(); i++){
			map.put(nameAndValues.get(i).elementAt(0), l.get(i));
		}
		return map;
	}
	
	private List<Boolean> set_private(Card card, List<Vector<String>> nameAndValues) throws SnmpException {
		List<Vector<String>> params = new ArrayList<Vector<String>>();
		for (Vector<String> v : nameAndValues) {
			String oid = getOidByName(v.elementAt(0), card) + getSuffix(card);
			Vector<String> _v = new Vector<String>();
			_v.add(oid);
			_v.add(v.elementAt(1));
			params.add(_v);
		}
		return sa.set(params);
	}
	
	@Override
	public boolean active() {
		//如果能获取到值，则表示网元能通讯
		try{
			sa.get(Ne.OID_UPTIME);
			return true;
		}catch(SnmpException e){
			return false;
		}
	}
	
	public void closeSession(){
		sa.close();
	}
	public String getIp() {
		return ip;
	}

	public void setIp(String ip) {
		this.ip = ip;
	}

}
